package com.jzy.weblog.jwt.service;
// 加载用户信息： 从数据源中加载用户的用户名、密码和角色等信息。
// 创建 UserDetails 对象： 根据加载的用户信息，创建一个 Spring Security 所需的 UserDetails 对象，包含用户名、密码、角色和权限等。
// JWT 模块下的服务类，负责用户认证服务。
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.jzy.weblog.common.domain.dos.UserDO;
import com.jzy.weblog.common.domain.dos.UserRoleDO;
import com.jzy.weblog.common.domain.mapper.UserMapper;
import com.jzy.weblog.common.domain.mapper.UserRoleMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserDetailServiceImpl implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Override
    public UserDetails loadUserByUsername(String username) {
        // 从数据库中查询
        UserDO userDO = userMapper.findByUsername(username);

        // 判断用户是否存在
        if (Objects.isNull(userDO)) {
            throw new UsernameNotFoundException("该用户不存在");
        }

        // 用户角色
        List<UserRoleDO> roleDOS = userRoleMapper.selectByUsername(username);
        String[] roleArr = null;

        // 转数组
        if (!CollectionUtils.isEmpty(roleDOS)) {
            List<String> roles = roleDOS.stream().map(p -> p.getRole()).collect(Collectors.toList());
            roleArr = roles.toArray(new String[roles.size()]);
        }

        // authorities 用于指定角色，这里写死为 ADMIN 管理员
        return User.withUsername(userDO.getUsername())
                .password(userDO.getPassword())
                .authorities(roleArr)
                .build();

    }
}
//用户发起登录请求，提交用户名和密码
//Spring Security 调用 UserDetailsService.loadUserByUsername(username)
//你返回一个 UserDetails 对象（包含密码、权限等）
//Spring Security 比较密码是否匹配
//如果匹配成功，生成 Authentication 对象，认证通过